﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects;

namespace Ecommerce.Model
{
    public class PedidoModel : BaseData
    {
        private static PedidoModel instance;

        private PedidoModel()
        {

        }

        public static PedidoModel Instance
        {
            get
            {
                if (instance == null)
                    instance = new PedidoModel();
                
                return instance;
            }
        }

        public void Inserir(tb_ped_pedido pedido)
        {
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                pedido.tb_pes_pessoa = db.tb_pes_pessoa.Where(x => x.pes_idt_pessoa == pedido.pes_idt_pessoa).First();
                pedido.tb_tpa_tipo_pagamento = db.tb_tpa_tipo_pagamento.Where(x => x.tpa_idt_tipo_pagamento == pedido.tpa_idt_tipo_pagamento).First();

                foreach (var itemPedido in pedido.tb_ipe_item_pedido)
                    itemPedido.tb_pro_produto = db.tb_pro_produto.Include("tb_cat_categoria").Where(x => x.pro_idt_produto == itemPedido.tb_pro_produto.pro_idt_produto).First();


                //Status do pedido
                tb_spl_status_pedido_log status = new tb_spl_status_pedido_log();
                status.spl_dat_criacao = DateTime.Now;
                status.tb_spe_status_pedido = db.tb_spe_status_pedido.Where(x => x.spe_cod_status_pedido.Equals("DIG")).First();
                status.tb_pes_pessoa = pedido.tb_pes_pessoa;
                pedido.tb_spl_status_pedido_log.Add(status);
                pedido.spe_idt_status_pedido = status.tb_spe_status_pedido.spe_idt_status_pedido;

                //Status Envio
                tb_spal_status_pagamento_log statusPagamento = new tb_spal_status_pagamento_log();
                statusPagamento.spal_dat_criacao = DateTime.Now;
                statusPagamento.tb_spp_status_pagamento_pedido = db.tb_spp_status_pagamento_pedido.Where(x => x.spp_cod_status_pagamento_pedido.Equals("PEN")).First();
                pedido.tb_spal_status_pagamento_log.Add(statusPagamento);
                pedido.spp_idt_status_pagamento_pedido = statusPagamento.tb_spp_status_pagamento_pedido.spp_idt_status_pagamento_pedido;

                //Status Pagamento
                tb_sel_status_envio_log statusEnvio = new tb_sel_status_envio_log();
                statusEnvio.sel_dat_criacao = DateTime.Now;
                statusEnvio.tb_sep_status_envio_pedido = db.tb_sep_status_envio_pedido.Where(x => x.sep_cod_status_envio_pedido.Equals("NEN")).First();
                pedido.tb_sel_status_envio_log.Add(statusEnvio);
                pedido.sep_idt_status_envio_pedido = statusEnvio.tb_sep_status_envio_pedido.sep_idt_status_envio_pedido;

                var ret = default(tb_ped_pedido);
                ret = db.tb_ped_pedido.Add(pedido);
                db.SaveChanges();

                //Gera o log do pedido
                var log = new tb_lrp_log_rastreamento_pedido();
                log.lrp_dat_criacao = DateTime.Now;
                log.lrp_des_log_rastreio_pedido = "Pedido inserido com sucesso!";
                log.ped_idt_pedido = ret.ped_idt_pedido;
                this.InserirLogPedido(log);
            }
        }

        public tb_tpa_tipo_pagamento ObterFormaPagamento(string codigo)
        {
            tb_tpa_tipo_pagamento item;
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                item = db.tb_tpa_tipo_pagamento.Where(x => x.tpa_cod_tipo_pagamento.Equals(codigo)).FirstOrDefault();
            }
            return item;
        }

        public List<tb_ped_pedido> ListarPedidosUsuario(int identificadorUsuario)
        {
            List<tb_ped_pedido> pedidos = new List<tb_ped_pedido>();
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                pedidos = db.tb_ped_pedido.Where(x => x.pes_idt_pessoa.Equals(identificadorUsuario)).ToList();

                foreach (tb_ped_pedido pedido in pedidos)
                    pedido.tb_spl_status_pedido_log.Add(this.ObterUltimoStatusPedido(pedido.ped_idt_pedido));
            }

            return pedidos;
        }

        public List<tb_ped_pedido> ListarPedidos()
        {
            List<tb_ped_pedido> pedidos = new List<tb_ped_pedido>();
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                pedidos = db.tb_ped_pedido.ToList();

                foreach (tb_ped_pedido pedido in pedidos)
                    pedido.tb_spl_status_pedido_log.Add(this.ObterUltimoStatusPedido(pedido.ped_idt_pedido));
            }

            return pedidos;
        }

        public List<tb_ped_pedido> ListarPedidos(FiltroPedidoModel filtro)
        {
            List<tb_ped_pedido> pedidos = new List<tb_ped_pedido>();
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                pedidos = db.tb_ped_pedido
                                            .Include("tb_sel_status_envio_log")
                                            .Include("tb_spal_status_pagamento_log")
                                            .Include("tb_spl_status_pedido_log")
                                            .Include("tb_sep_status_envio_pedido")
                                            .Include("tb_spe_status_pedido")
                                            .Include("tb_spp_status_pagamento_pedido")
                                            .Where(x => filtro.IdentificadorPedido.HasValue ? x.ped_idt_pedido.Equals(filtro.IdentificadorPedido.Value) : 1 == 1 &&
                                                        filtro.DataInicio.HasValue ? x.ped_dat_criacao >= filtro.DataInicio.Value : 1 == 1 &&
                                                        filtro.DataFim.HasValue ? x.ped_dat_criacao <= filtro.DataFim.Value : 1 == 1 &&
                                                        filtro.IdentificadorStatusEnvio.HasValue ? x.sep_idt_status_envio_pedido == filtro.IdentificadorStatusEnvio.Value : 1 == 1 &&
                                                        filtro.IdentificadorStatusPagamento.HasValue ? x.spp_idt_status_pagamento_pedido == filtro.IdentificadorStatusPagamento.Value : 1 == 1 &&
                                                        filtro.IdentificadorStatusPedido.HasValue ? x.spe_idt_status_pedido == filtro.IdentificadorStatusPedido.Value : 1 == 1
                                            ).ToList();

                foreach (tb_ped_pedido pedido in pedidos)
                {
                    pedido.tb_spl_status_pedido_log = new List<tb_spl_status_pedido_log>();
                    pedido.tb_spl_status_pedido_log.Add(this.ObterUltimoStatusPedido(pedido.ped_idt_pedido));

                    pedido.tb_sel_status_envio_log = new List<tb_sel_status_envio_log>();
                    pedido.tb_sel_status_envio_log.Add(this.ObterUltimoStatusEnvio(pedido.ped_idt_pedido));

                    pedido.tb_spal_status_pagamento_log = new List<tb_spal_status_pagamento_log>();
                    pedido.tb_spal_status_pagamento_log.Add(this.ObterUltimoStatusPagamento(pedido.ped_idt_pedido));
                }
            }

            return pedidos;
        }

        public void InserirStatus(tb_spl_status_pedido_log statusPedido)
        {
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                statusPedido.tb_pes_pessoa = db.tb_pes_pessoa.Where(x => x.pes_idt_pessoa == statusPedido.pes_idt_pessoa).First();
                statusPedido.tb_spe_status_pedido = db.tb_spe_status_pedido.Where(x => x.spe_idt_status_pedido == statusPedido.spe_idt_status_pedido).First();

                db.tb_spl_status_pedido_log.Add(statusPedido);
                db.SaveChanges();
            }
        }

        public void InserirStatusPagamento(tb_spal_status_pagamento_log statusPagamento)
        {
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                statusPagamento.tb_spp_status_pagamento_pedido = db.tb_spp_status_pagamento_pedido.Where(x => x.spp_idt_status_pagamento_pedido == statusPagamento.spp_idt_status_pagamento_pedido).First();
                db.tb_spal_status_pagamento_log.Add(statusPagamento);
                db.SaveChanges();
            }
        }

        public void InserirStatusEnvio(tb_sel_status_envio_log statusEnvio)
        {
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                statusEnvio.tb_sep_status_envio_pedido = db.tb_sep_status_envio_pedido.Where(x => x.sep_idt_status_envio_pedido == statusEnvio.sep_idt_status_envio_pedido).First();
                db.tb_sel_status_envio_log.Add(statusEnvio);
                db.SaveChanges();
            }
        }

        public tb_spl_status_pedido_log ObterUltimoStatusPedido(int identificadorPedido)
        {
            tb_spl_status_pedido_log item;
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                item = db.tb_spl_status_pedido_log.Include("tb_spe_status_pedido").Where(x => x.ped_idt_pedido == identificadorPedido).OrderByDescending(x=> x.spl_dat_criacao).FirstOrDefault();
            }
            return item;
        }

        private tb_spe_status_pedido ObterStatus(int identificador)
        {
            tb_spe_status_pedido status = new tb_spe_status_pedido();
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                status = db.tb_spe_status_pedido.Where(x => x.spe_idt_status_pedido == identificador).FirstOrDefault();
            }
            return status;
        }

        public tb_ped_pedido Obter(int identificadorPedido)
        {
            tb_ped_pedido pedido = default(tb_ped_pedido);

            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                pedido = db.tb_ped_pedido.Include("tb_spl_status_pedido_log").
                    Include("tb_tpa_tipo_pagamento").
                    Include("tb_ipe_item_pedido").
                    Include("tb_ien_informacao_envio").
                    Where(x => x.ped_idt_pedido == identificadorPedido).FirstOrDefault();

                //Obtem o ultimo status do pedido
                foreach (tb_spl_status_pedido_log item in pedido.tb_spl_status_pedido_log)
                    item.tb_spe_status_pedido = this.ObterStatus(item.spe_idt_status_pedido);

                //Obtem os dados de endereço de envio
                pedido.tb_ien_informacao_envio.First().tb_end_endereco = EnderecoModel.Instance.Obter(pedido.tb_ien_informacao_envio.First().end_idt_endereco);

                //Obtenho o produto
                foreach (tb_ipe_item_pedido item in pedido.tb_ipe_item_pedido)
                    item.tb_pro_produto = new ProdutoModel().Obter(item.pro_idt_produto);
            }

            return pedido;
        }

        public void AtualizarInformacaoEnvio(tb_ien_informacao_envio informacaoEnvio)
        {
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                db.tb_ien_informacao_envio.Attach(informacaoEnvio);
                db.Entry(informacaoEnvio).State = System.Data.EntityState.Modified;
                db.SaveChanges();
            }
        }

        public List<tb_ipe_item_pedido> ListarItensPedido(int identificadorPedido)
        {
            List<tb_ipe_item_pedido> itens = new List<tb_ipe_item_pedido>();
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false)){
                itens = db.tb_ipe_item_pedido.Include("tb_pro_produto").Where(x => x.ped_idt_pedido.Equals(identificadorPedido)).ToList();

                foreach (tb_ipe_item_pedido item in itens)
                    item.tb_pro_produto.tb_cat_categoria = db.tb_cat_categoria.Where(x => x.cat_idt_categoria.Equals(item.tb_pro_produto.cat_idt_categoria)).FirstOrDefault();
            }

            return itens;
        }

        public void InserirLogPedido(tb_lrp_log_rastreamento_pedido log)
        {
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                db.tb_lrp_log_rastreamento_pedido.Add(log);
                db.SaveChanges();
            }
        }

        public List<tb_lrp_log_rastreamento_pedido> ListarLogPedido(int identificadorPedido)
        {
            List<tb_lrp_log_rastreamento_pedido> logs = new List<tb_lrp_log_rastreamento_pedido>();
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
                logs = db.tb_lrp_log_rastreamento_pedido.Where(x => x.ped_idt_pedido == identificadorPedido).ToList();

            return logs.OrderByDescending(x => x.lrp_dat_criacao).ToList();
        }


        public List<tb_spe_status_pedido> ListarStatusPedido()
        {
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
                return db.tb_spe_status_pedido.ToList();
        }

        public tb_spe_status_pedido ObterStatusPedido(string codigoStatus)
        {
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
                return db.tb_spe_status_pedido.Where(x=> x.spe_cod_status_pedido.Equals(codigoStatus)).FirstOrDefault();
        }

        public List<tb_spp_status_pagamento_pedido> ListarStatusPagamento()
        {
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
                return db.tb_spp_status_pagamento_pedido.ToList();
        }

        public tb_spal_status_pagamento_log ObterUltimoStatusPagamento(int identificadorPedido)
        {
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
                return db.tb_spal_status_pagamento_log.Include("tb_spp_status_pagamento_pedido").Where(x => x.ped_idt_pedido == identificadorPedido).OrderByDescending(x => x.spal_dat_criacao).FirstOrDefault();
        }

        public tb_spp_status_pagamento_pedido ObterStatusPagamento(string codigoStatusPagamento)
        {
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
                return db.tb_spp_status_pagamento_pedido.Where(x=> x.spp_cod_status_pagamento_pedido.Equals(codigoStatusPagamento)).First();
        }

        public List<tb_sep_status_envio_pedido> ListarStatusEnvio()
        {
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
                return db.tb_sep_status_envio_pedido.ToList();
        }

        public tb_sel_status_envio_log ObterUltimoStatusEnvio(int identificadorPedido)
        {
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
                return db.tb_sel_status_envio_log.Include("tb_sep_status_envio_pedido").Where(x => x.ped_idt_pedido == identificadorPedido).OrderByDescending(x => x.sel_dat_criacao).FirstOrDefault();
        }

        public List<ListarPedidoPorStatus_Result> ListarPedidoPorStatus()
        {
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
                return db.ListarPedidoPorStatus().ToList();
        }

        public List<ObterProdutosMaisVendidos_Result> ListarProdutosMaisVendidos()
        {
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
                return db.ObterProdutosMaisVendidos().ToList();
        }

        public tb_tpa_tipo_pagamento ObterTipoPagamento(int identificador)
        {
            tb_tpa_tipo_pagamento item;
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                item = db.tb_tpa_tipo_pagamento.Where(x => x.tpa_idt_tipo_pagamento == identificador).FirstOrDefault();
            }
            return item;
        }

        public void AtualizarURLBoleto(int idPedido, string url)
        {
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                tb_ped_pedido pedido = db.tb_ped_pedido.Where(p => p.ped_idt_pedido == idPedido).First();
                pedido.ped_des_caminho_boleto = url;
                db.SaveChanges();
            }
        }

        public void AtualizarNumeroAutorizacao(int idPedido, string numeroAutorizacao)
        {
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                tb_ped_pedido pedido = db.tb_ped_pedido.Where(p => p.ped_idt_pedido == idPedido).First();
                pedido.ped_num_autorizacao_cartao_credito = numeroAutorizacao;
                db.SaveChanges();
            }
        }

        public List<tb_ien_informacao_envio> ListarEnvioPedido(FiltroEnvioPedidoModel filtro)
        {
            List<tb_ien_informacao_envio> envios = new List<tb_ien_informacao_envio>();
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                envios = db.tb_ien_informacao_envio
                                            .Include("tb_tra_transportadora")
                                            .Include("tb_end_endereco")
                                            .Include("tb_ped_pedido")
                                            .Where(x => filtro.NumeroPedido.HasValue ? x.ped_idt_pedido.Equals(filtro.NumeroPedido.Value) : 1 == 1 &&
                                                        filtro.DataInicio.HasValue ? x.ien_dat_envio_pedido >= filtro.DataInicio.Value : 1 == 1 &&
                                                        filtro.DataFim.HasValue ? x.ien_dat_recebimento_pedido <= filtro.DataFim.Value : 1 == 1 &&
                                                        !String.IsNullOrEmpty(filtro.CodigoRastreamento) ? x.ien_cod_rastreamento == filtro.CodigoRastreamento : 1 == 1 &&
                                                        !String.IsNullOrEmpty(filtro.SiglaUF) ? x.tb_end_endereco.end_sig_uf == filtro.SiglaUF : 1 == 1 &&
                                                        !String.IsNullOrEmpty(filtro.NomeCidade) ? x.tb_end_endereco.end_nom_cidade.Contains(filtro.NomeCidade) : 1 == 1
                                            ).ToList();
            }

            return envios;
        }
    }
}
